package com.li.springbootproject.service.user.impl;

import com.alibaba.fastjson.JSON;
import com.li.springbootproject.config.datasource.DataSourceType;
import com.li.springbootproject.config.datasource.MyDataSource;
import com.li.springbootproject.domain.User;
import com.li.springbootproject.domain.common.BackResult;
import com.li.springbootproject.domain.event.UserEvent;
import com.li.springbootproject.mapper.UserMapper;
import com.li.springbootproject.service.user.UserService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * @Description：
 * @Author：LiDong
 * @Create：2021/3/15
 * @Version：1.0.0
 */
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ApplicationEventPublisher publisher;


    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);

    /**
     * 批量插入
     *
     * @return
     */
    @Override
    public Object insertUserBatch() {

        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 3200; i++) {
            User user = new User();
            user.setUsername("用户" + i);
            Random random = new Random();
            user.setGender(random.nextInt(10) % 2);
            userList.add(user);
        }
        List<User> insertList = new ArrayList<>();
        userList.forEach(x -> {
            insertList.add(x);
            if (insertList.size() == 1000) {
                userMapper.insertUserBatch(insertList);
                insertList.clear();
            }
        });
        if (!insertList.isEmpty()) {
            userMapper.insertUserBatch(insertList);
        }
        return "总共：" + insertList.size() + "条数据存入成功！";
    }

    /**
     * in 1000 使用
     *
     * @return
     */
    @Override
    public BackResult inSqlUse() {
        BackResult backResult = new BackResult();
        try {
            List<String> list = new ArrayList<>();
            for (int i = 1; i <= 100; i++) {
                list.add(String.valueOf(i));
            }
            List<Object> objects = userMapper.inSqlUse(list);
            backResult.setSuccess(true);
            backResult.setData(objects);
        } catch (Exception e) {
            log.info(e.getMessage());
            backResult.setMessage(e.getMessage());
            backResult.setSuccess(false);
        }
        return backResult;
    }

    /**
     * SpringBoot Event 使用
     *
     * @return
     */
    @Override
    @MyDataSource(value = DataSourceType.MASTER)
    public BackResult testEvent() {
        BackResult backResult = new BackResult();
        try {
            // 向user 表插入数据
            insertUsers();
            log.info("------------>");
            // 添加user插入对象操作
            sendInsertUser();
            backResult.setSuccess(true);
            backResult.setMessage("操作成功!");
        } catch (Exception e) {
            backResult.setMessage(e.getMessage());
            backResult.setSuccess(false);
        }
        return backResult;
    }

    @Override
    @MyDataSource(value = DataSourceType.SLAVE)
    public BackResult testDatasource() {
        BackResult backResult = new BackResult();
        List<Map<String, String>> maps = userMapper.queryUsers();
        backResult.setData(maps);
        backResult.setSuccess(true);
        backResult.setMessage("OK");
        return backResult;
    }

    /**
     * 发布插入user表的事件
     */
    private void sendInsertUser() {
        User user = new User();
        user.setId(20210317);
        user.setUsername("测试张三");
        UserEvent<User> userEvent = new UserEvent<>(user);
        // 发布事件
        publisher.publishEvent(userEvent);

    }

    /**
     * 监听插入User的事件 : 在上个事务提交之后在执行
     */
    @Async
    @TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT, fallbackExecution = true)
    public void insertUserLinster(UserEvent<User> userEvent) {
        User data = userEvent.getData();
        String message = String.format("get user message: %s", JSON.toJSONString(data));
        log.info(message);
        // 后续操作；继续处理
    }


    /**
     * 插入开启事物
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertUsers() {
        insertUserBatch();
    }
}
